import {type Money, parseMoney} from "./Money.ts";
import {buildUserBuff, type UserBuff, UserBuffType} from "./UserBuff.ts";
import {type Timestamp, TS} from "./Timestamp.ts";
import {decode} from "../utils/StrUtils.ts";
import {AccountStatus, buildAccountStatus,} from "./AccountStatus.ts";
import type {TinyForum} from "./Forum.ts";
import {transform} from "../utils/ObjectUtils.ts";
import {type BbsCodeNode, parseContent} from "./BbsCodeNode.ts";

export interface TinyUserInfo {
    userId: number
    username: string
}

export interface SimpleUserInfo extends TinyUserInfo {
    avatars: string[] | undefined
}

const parseAvatars = (avatarString: string): string[] | undefined => {
    const avatar = avatarString && avatarString.trim() ? avatarString.replace("http:", "https:") : undefined

    if (!avatar) {
        return undefined;
    }

    if (avatar.includes("|.a")) {
        const split = avatar.split("|.a");
        // 前缀
        const prefix = split[0].substring(0, split[0].lastIndexOf("/"));
        // 添加前缀
        return split.map(it => prefix + it.replace(prefix, ""));
    } else if (avatar.includes("|")) {
        return avatar.split("|");
    }

    return [avatar];
};

export const buildSimpleUserInfo = (data: any): SimpleUserInfo => ({
    userId: data.uid,
    username: data.username,
    avatars: parseAvatars(data.avatar)
})

export interface BaseUserInfo extends SimpleUserInfo {
    buffs: UserBuff[] | undefined
    groupId: number
    memberId: number
    honorString: string
    money: Money
    medalId: number[]
    regDatetime: Timestamp | undefined
    postCount: number
    prestige: number
    signature: string | undefined
    signatureNodes: BbsCodeNode[] | undefined
    remark: any
    status: AccountStatus | undefined
    avatarBuffId: number | undefined
    isMuted: boolean
}

const buildBaseUserInfo = (data: any): BaseUserInfo => {
    const simpleUserInfo = buildSimpleUserInfo(data);

    const bitData: number | undefined = data.bit || data.bit_data
    const buffs = transform<UserBuff>(data.buffs, (it: any) => buildUserBuff(it))

    const avatarBuffId = buffs && [...buffs].reverse().find((it: any) => it.type == UserBuffType.AVATAR_CHANGED)?.extraData
    const isMuted = buffs && !!buffs.find((it: any) => it.type == UserBuffType.MUTED) || false
    const medalId = data.medal && data.medal != '0' && data.medal != 0 && data.medal.toString().split(',').map(Number)

    return {
        ...simpleUserInfo,
        buffs, medalId,
        groupId: data.groupid || data.gid,
        memberId: data.memberid,
        honorString: data.honor,
        money: parseMoney(data.money),
        regDatetime: TS(data.regdate),
        postCount: data.posts || data.postnum,
        prestige: data.rvrc || data.fame,
        signature: decode(data.sign || data.signature),
        signatureNodes: parseContent(data.sign || data.signature),
        remark: data.remark,
        status: bitData && buildAccountStatus(bitData!!),
        avatarBuffId, isMuted
    }
}

export interface UserInfo extends BaseUserInfo {
    userForum: string | undefined
    reputation: {
        [key: number]: number
    }
}

export const buildUserInfo = (data: any): UserInfo => {
    const baseUserInfo = buildBaseUserInfo(data);
    const reputation: { [key: number]: number } = {}
    if (data.reputation) {
        data.reputation.split(",").forEach((p: any) => {
            const [id, value] = p.split("_")
            reputation[Number(id)] = Number(value)
        })
    }

    return {
        ...baseUserInfo,
        userForum: decode(data.site),
        reputation,
    }
}

export interface Reputation {
    name: string
    value: number
    description: string
}

export interface UserDetail extends BaseUserInfo {
    adminForums: TinyForum[] | undefined
    followed: boolean
    followCount: number
    followedCount: number
    groupName: string
    ipLocation: string
    userForum: string
    usernameChanged: boolean
    email: string
    reputations: Reputation[] | undefined
    background: string
    totalAgree: number | undefined
    totalGifts: number | undefined
}

export const buildUserDetail = (data: any): UserDetail => {
    const userInfo = buildBaseUserInfo(data);
    const moreInfo = transform(data.more_info, (it: any) => {
        return {
            type: it.type,
            data: it.data
        }
    })
    const reputations = transform<Reputation>(data.reputation, (it: any) => {
        return {
            name: it[0],
            value: it[1],
            description: it[2]
        }
    })


    return {
        ...userInfo, reputations,
        adminForums: data.adminForums && Object.keys(data.adminForums).map(id => {
            return {id: Number(id), name: decode(data.adminForums[id]),}
        }),
        followed: !!data.follow,
        followCount: data.follow_num,
        followedCount: data.follow_by_num,
        groupName: data.group,
        ipLocation: data.ipLoc,
        userForum: data.userForum && decode(data.userForum[1]),
        usernameChanged: data.usernameChanged,
        email: data.email,
        background: data.ucpbg,
        totalAgree: moreInfo && moreInfo.find((i: any) => i.type == 8)?.data,
        totalGifts: moreInfo && moreInfo.find((i: any) => i.type == 9)?.data
    }
}

export const buildUserDetailHtml = (html: string): UserDetail => {
    const ucp = /var __UCPUSER =(.+);/.exec(html)?.[1];
    if (!ucp) return {} as UserDetail
    const json = JSON.parse(ucp)
    // console.log(json)
    return buildUserDetail(json)
}

export interface OldName {
    username: string
    before: Timestamp | undefined
}

export const buildOldName = (data: any): OldName => {
    return {
        username: data.username,
        before: TS(data.time)
    }
}